import { nextTick, onUnmounted, watch, type ComputedRef, type Ref } from 'vue';
import { getMaxHeight, getMinHeight, getMinHeightColumnIndex } from '../utils';

interface ParamsType {
  data: ComputedRef<Record<string, any>[] | null>;
  columns: ComputedRef<number>;
  containerLeft: Ref<number>;
  picturePreReading: boolean;
  colGap: number;
  rowGap: number;
  // colHeight: Ref<Record<string, number>>;
  itemHeights: Ref<number[]>;
  containerHeight: Ref<number>;
  getItemHeightsAsync: () => Promise<number[]>;
  updateItemHeightAsync: () => Promise<number[]>;
  getItemHeightsSync: () => number[];
  updateItemHeightsSync: () => number[];
  colHeight: ComputedRef<Record<string, number>>;
  colWidth: ComputedRef<number>;
}

export default function useImageLocation({
  data,
  columns,
  containerLeft,
  colGap,
  rowGap,
  containerHeight,
  picturePreReading,
  itemHeights,
  getItemHeightsAsync,
  getItemHeightsSync,
  updateItemHeightsSync,
  updateItemHeightAsync,
  colHeight,
  colWidth
}: ParamsType) {
  onUnmounted(() => {
    data.value?.forEach(item => {
      item._style = null;
    });
  });

  watch(
    () => data.value,
    val => {
      nextTick(async () => {
        if (picturePreReading) {
          itemHeights.value = await getItemHeightsAsync().then(res => res);
        } else {
          itemHeights.value = getItemHeightsSync();
        }

        if (val?.length) {
          setImageItemLocation(itemHeights.value);
        }
      });
    },
    {
      deep: true,
      immediate: true
    }
  );

  watch(columns, () => {
    setTimeout(async () => {
      data.value?.forEach(item => {
        // 避免重复计算
        item._style = null;
      });

      if (picturePreReading) {
        itemHeights.value = await updateItemHeightAsync().then(res => res);
      } else {
        itemHeights.value = updateItemHeightsSync();
      }

      if (data.value?.length) {
        setImageItemLocation(itemHeights.value);
      }
    }, 150);
  });

  function setImageItemLocation(itemHeights: number[]) {
    data.value?.forEach((item, index) => {
      // 避免重复计算
      if (item._style) {
        return;
      }

      item._style = {
        top: getMinHeight(colHeight.value),
        left: getItemLeft(colHeight.value)
      };

      // 列高自增
      increaseColHeight(index, colHeight, itemHeights);
    });

    containerHeight.value = getMaxHeight(colHeight.value);

    function increaseColHeight(
      index: number,
      columnHeights: Ref<Record<string, number>>,
      itemHeights: number[]
    ) {
      const minColIndex = getMinHeightColumnIndex(
        columnHeights.value
      ) as number;

      columnHeights.value[minColIndex] += itemHeights[index] + rowGap;
    }

    function getItemLeft(columnHeights: Record<string, number>) {
      const minColIndex = getMinHeightColumnIndex(columnHeights) as number;

      return minColIndex * (colGap + colWidth.value) + containerLeft.value;
    }
  }

  // return { setImageItemLocation };
}
